﻿#!/usr/bin/python
# -*- coding:utf-8 -*-
'''
GPIO17 >> 黄
GPIO18 >> 蓝
'''
import datetime
import os
import SSD1306
import time
import socket
import psutil
import multiprocessing
import RPi.GPIO as GPIO
from PIL import Image, ImageDraw, ImageFont


class Fan:
    SLEEP = 1
    I = 5
    NIGHT_SLEEP = 300
    PIN_FAN = 18
    SPEED_BASE = 50
    SPEED_STEP = 1
    THRESHOLD_TEMP = 35
    TEMP_FILE = "/sys/class/thermal/thermal_zone0/temp"

    def __init__(self):
        self.speed_init = 0
        self.oled = None
        self.p = None
        self.draw = None
        self.font = None
        self.init()

    def init(self):
        GPIO.setwarnings(False)
        GPIO.cleanup()
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.PIN_FAN, GPIO.OUT)
        self.oled = SSD1306.SSD1306()
        self.oled.Init()
        self.oled.ClearBlack()
        self.p = GPIO.PWM(self.PIN_FAN, 10)
        self.p.start(self.speed_init)

        # Create blank image for drawing.
        self.image = Image.new('1', (self.oled.width, self.oled.height), "WHITE")
        self.draw = ImageDraw.Draw(self.image)
        self.font = ImageFont.load_default()

    def get_localhost(self):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(('8.8.8.8', 80))
            localhost = s.getsockname()[0]
        except Exception:
            localhost = ''
        return localhost

    def change_fan_speed(self, temp):
        '''
        调整风速
        :param temp: 温度
        :return:
        '''
        speed = (self.SPEED_BASE + (
                temp - self.THRESHOLD_TEMP) * self.SPEED_STEP) if temp >= self.THRESHOLD_TEMP else 0
        if speed > 100:
            speed = 100
        if self.speed_init != speed:
            self.p.ChangeDutyCycle(speed)
            self.speed_init = speed
        return

    def get_cpu_temp(self):
        with open(self.TEMP_FILE) as f:
            cpu_temp = f.read()
        return round(float(cpu_temp) / 1000, 2)

    def cpu_usage(self):
        # cpuLoad = os.getloadavg()
        # return cpuLoad[0] / multiprocessing.cpu_count()

        cmd = "top -bn1 | grep load | awk '{printf \"%.2f\", $(NF-2)}'"
        CPU = os.popen(cmd).read()
        return float(CPU) / 100

    def ram_usage(self):
        ramStat = psutil.virtual_memory()
        ramTot = ramStat.total >> 20
        ramUsd = ramStat.used >> 20
        return "RAM: {}/{} MB".format(ramUsd, ramTot)

    def show_image(self, localhost, temp, cpu):
        print(localhost, temp, cpu)
        try:
            self.draw.rectangle((0, 0, 128, 32), fill=1)
            self.draw.text((0, 0), "CPU:{:.1%}  Temp:{:.1f}".format(cpu, temp), font=self.font, fill=0)
            self.draw.text((0, 10), self.ram_usage(), font=self.font, fill=0)
            # self.draw.text((0, 16), self.disk_usage('/'), font=self.font, fill=0)
            self.draw.text((0, 20), "IP:{}".format(localhost), font=self.font, fill=0)

            self.oled.ShowImage(self.oled.getbuffer(self.image.rotate(180)))
        except IOError as e:
            self.oled.Closebus()
            print(e)

        except KeyboardInterrupt:
            print("ctrl + c:")
            self.oled.Closebus()

    def bytes2human(self, n):
        """
        >>> bytes2human(10000)
        '9K'
        >>> bytes2human(100001221)
        '95M'
        """
        symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
        prefix = {}
        for i, s in enumerate(symbols):
            prefix[s] = 1 << (i + 1) * 10
        for s in reversed(symbols):
            if n >= prefix[s]:
                value = int(float(n) / prefix[s])
                return '%s%s' % (value, s)
        return "%sB" % n

    def disk_usage(self, dir):
        usage = psutil.disk_usage(dir)
        return "SD:%s %.0f%%" \
            % (self.bytes2human(usage.used), usage.percent)

    def main(self, allTime=False):
        hour = datetime.datetime.now().hour
        localhost = self.get_localhost()
        cpu = self.cpu_usage()
        temp = self.get_cpu_temp()
        self.I += 1
        if self.I >= 5:
            self.change_fan_speed(temp)
            self.I = 0
        if allTime is False:
            if hour <= 21 and hour >= 7:
                self.show_image(localhost, temp, cpu)
                time.sleep(self.SLEEP)
            else:
                # self.p.ChangeDutyCycle(0)
                self.oled.ClearBlack()
                time.sleep(self.NIGHT_SLEEP)
            pass
        return

    def run(self, allTime=False):
        while True:
            self.main(allTime)
        pass


if __name__ == '__main__':
    fan = Fan()
    fan.run()
